{
 "cells": [
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "### RunnableParallel 场景案例设计\n",
    "\n",
    "#### 场景描述\n",
    "假设我们正在开发一个智能客服系统，该系统需要同时处理用户的多个请求。具体来说，系统需要并行执行以下任务：\n",
    "1. **情感分析**：分析用户输入的情感倾向（正面、负面、中性）。\n",
    "2. **意图识别**：识别用户输入的意图（咨询、投诉、建议等）。\n",
    "3. **信息检索**：从知识库中检索与用户输入相关的信息。\n",
    "\n",
    "通过 `RunnableParallel`，我们可以并行执行这三个任务，然后将结果合并，以便生成更全面的响应。\n",
    "\n",
    "#### 实现步骤\n",
    "\n",
    "1. **导入必要的库**：\n",
    "2. **定义各个子链**：\n",
    "   - **情感分析链**：使用预训练的情感分析模型。\n",
    "   - **意图识别链**：使用预训练的意图识别模型。\n",
    "   - **信息检索链**：从知识库中检索信息。\n",
    "3. **使用 `RunnableParallel` 并行执行这些子链**。\n",
    "4. **合并结果**：将各个子链的结果合并，生成最终的响应。\n",
    "\n",
    "#### 代码实现"
   ],
   "id": "1b62cda64a5a5f3a"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-04-13T12:59:55.407549Z",
     "start_time": "2025-04-13T12:59:49.590556Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from langchain_community.vectorstores import DocArrayInMemorySearch\n",
    "from langchain_core.runnables import RunnableParallel, RunnableLambda, RunnablePassthrough\n",
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "from langchain_ollama import ChatOllama\n",
    "from langchain_core.output_parsers import StrOutputParser\n",
    "from operator import itemgetter\n",
    "from langchain_ollama import OllamaEmbeddings\n",
    "\n",
    "# 初始化模型\n",
    "model = ChatOllama(base_url=\"http://10.2.4.31:11434\", model=\"qwen2.5:latest\")\n",
    "\n",
    "# 1. 情感分析链\n",
    "sentiment_template = \"\"\"你是一位优秀的意图分析专家，请分析以下文本的情感倾向（正面、负面、中性）：\n",
    "{input}\n",
    "\"\"\"\n",
    "sentiment_chain = ChatPromptTemplate.from_template(sentiment_template) | model | StrOutputParser()\n",
    "\n",
    "# 2. 意图识别链\n",
    "intent_template = \"\"\"你是一位优秀的意图分析专家，请识别以下文本的意图（咨询、投诉、建议等）：\n",
    "{input}\n",
    "\"\"\"\n",
    "intent_chain = ChatPromptTemplate.from_template(intent_template) | model | StrOutputParser()\n",
    "\n",
    "# 3. 信息检索链\n",
    "retrieval_template = \"\"\"你是一位问题解决专家，请从以下内容中检索信息：\n",
    "{context}\n",
    "检索的内容为：\n",
    "{input}\n",
    "\"\"\"\n",
    "\n",
    "embeddings = OllamaEmbeddings(\n",
    "    model=\"quentinz/bge-large-zh-v1.5:latest\",\n",
    "    base_url=\"http://10.2.4.31:11434\",\n",
    ")\n",
    "\n",
    "vectorstore = DocArrayInMemorySearch.from_texts(\n",
    "    [\"产品属于组装机，提供经济补偿\", \"产品有质量问题，提供七天无理由退货\"],\n",
    "    embedding=embeddings\n",
    ")\n",
    "\n",
    "retriever = vectorstore.as_retriever()\n",
    "set_retriever_parallel = RunnableParallel({\n",
    "    \"context\": retriever,\n",
    "    \"input\": RunnablePassthrough()\n",
    "})\n",
    "\n",
    "retrieval_chain = set_retriever_parallel | ChatPromptTemplate.from_template(retrieval_template) | model | StrOutputParser()\n",
    "\n",
    "# retrieval_chain.invoke({\"input\": \"我最近购买的产品有问题，希望你们能尽快解决。\"})\n",
    "# 并行执行三个链\n",
    "parallel_chain = RunnableParallel(\n",
    "    sentiment=sentiment_chain,\n",
    "    intent=intent_chain,\n",
    "    retrieval=retrieval_chain\n",
    ")\n",
    "\n",
    "# 合并结果\n",
    "def merge_results(results):\n",
    "    sentiment = results[\"sentiment\"]\n",
    "    intent = results[\"intent\"]\n",
    "    retrieval = results[\"retrieval\"]\n",
    "    return f\"情感倾向: {sentiment}\\n意图: {intent}\\n检索结果: {retrieval}\"\n",
    "\n",
    "final_chain = parallel_chain | RunnableLambda(merge_results)\n",
    "\n",
    "# 测试\n",
    "user_input = \"我最近购买的产品有问题，希望你们能尽快解决。\"\n",
    "response = final_chain.invoke(user_input)\n",
    "print(response)"
   ],
   "id": "571045206e963183",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "情感倾向: 根据提供的文本内容，“我最近购买的产品有问题，希望你们能尽快解决。”这句话表达了一种轻微的不满和期待解决问题的心情。因此，从情感倾向上来看，可以被归类为“负面”，因为提到了“问题”这个词语，暗示了顾客对产品或者服务的不满意度。但同时也表达了希望得到积极回应的愿望，说明顾客并没有完全失望或愤怒。\n",
      "意图: 根据您提供的文本，“我最近购买的产品有问题，希望你们能尽快解决。” 这句话表达了用户遇到了产品问题，并期望得到商家或服务提供商的帮助和解决方案。因此，这段话的意图可以归类为“投诉”，因为客户对商品质量或服务表示了不满，并请求快速处理问题。\n",
      "检索结果: 根据您提供的文档信息，您的情况可以参照以下内容处理：\n",
      "\n",
      "1. 如果您的产品存在质量问题，您可以享受七天无理由退货的权利；\n",
      "2. 若您的产品属于组装机，则可能需要按照相关规定提供经济补偿。\n",
      "\n",
      "建议您首先确认所购产品的具体问题性质，以便采取相应的解决措施。如遇到任何疑问或需要进一步的帮助，请随时联系客服团队。\n"
     ]
    }
   ],
   "execution_count": 19
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "\n",
    "#### 运行结果\n",
    "```\n",
    "情感倾向: 负面\n",
    "意图: 投诉\n",
    "检索结果: 对于您遇到的问题，我们非常重视。请您提供具体的订单号和问题描述，我们将尽快为您处理。\n",
    "```\n",
    "\n",
    "\n",
    "#### 解释\n",
    "1. **情感分析链**：分析用户输入的情感倾向，结果为“负面”。\n",
    "2. **意图识别链**：识别用户输入的意图，结果为“投诉”。\n",
    "3. **信息检索链**：从知识库中检索与用户输入相关的信息，结果为具体的解决方案提示。\n",
    "4. **合并结果**：将三个子链的结果合并，生成最终的响应。\n",
    "\n",
    "通过这种方式，我们可以高效地并行处理用户的多个请求，提高系统的响应速度和处理能力。"
   ],
   "id": "6a8e5beb42cfdb2a"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
